package com.nulldev.util.VariableAPI.util.random.tests;

import com.nulldev.util.JVM.Arguments;
import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.util.random.RandomAccelMethod;
import com.nulldev.util.VariableAPI.util.random.nRandom;
import com.nulldev.util.data.Variables;
import com.nulldev.util.data.Arrays.maps.FastMaps;
import com.nulldev.util.internal.testing.Test;
import com.nulldev.util.internal.testing.TestManager;
import com.nulldev.util.io.IOUtils;

public class RNGAccelMethodBenchmark extends TestManager {

	public static class RNGAccelMethodTest extends Test<Object> {

		private final RandomAccelMethod accelMethod;

		public RNGAccelMethodTest(final RandomAccelMethod accelMethod) {
			this.accelMethod = Variables.requireNonNullObject(accelMethod, "accelMethod");
		}

		@Override
		public void test() throws Throwable {
			final nRandom nr = new nRandom(this.accelMethod);
			final byte[] c = new byte[IOUtils.MEMORY_ALLOC_BUFFER];
			// warm up
			for (int i = 0; i < 64; i++)
				nr.nextBytes(c);
			// actual run
			final long s = System.currentTimeMillis();
			for (int i = 0; i < 64; i++)
				nr.nextBytes(c);
			final long e = System.currentTimeMillis();
			JVM.println(this.accelMethod + "\t - " + (e - s) + " ms");
			IOUtils.closeQuietly(nr);
			this.finish((e - s));
		}

	}

	public RNGAccelMethodBenchmark() {
		super(FastMaps.fixedUniMap(new Object[][]
			{
					{ "default", new RNGAccelMethodTest(RandomAccelMethod.NO_ACCELERATION) },
					{ "unix", new RNGAccelMethodTest(RandomAccelMethod.UNIX_RANDOM) },
					{ "fast-rng", new RNGAccelMethodTest(RandomAccelMethod.FAST_RANDOM) },
					{ "faster-rng-taus", new RNGAccelMethodTest(RandomAccelMethod.FASTER_RNG_TAUS) },
					{ "faster-rng-twister", new RNGAccelMethodTest(RandomAccelMethod.FASTER_RNG_TWISTER) },
					{ "faster-rng-well", new RNGAccelMethodTest(RandomAccelMethod.FASTER_RNG_WELL512) },
					{ "faster-rng-mrg32k3a", new RNGAccelMethodTest(RandomAccelMethod.FASTER_RNG_MRG32K3A) } }));
	}

	public static void main(String[] args) {
		Arguments.setup(args);
		JVM.println("UNIX_RANDOM_LOCAL_FIO: " + nRandom.UNIX_RANDOM_LOCAL_FIO);
		JVM.println("UNIX_RANDOM_LOCAL_FIO_BUFFERING: " + nRandom.UNIX_RANDOM_LOCAL_FIO_BUFFERING);
		new RNGAccelMethodBenchmark().run();
	}
}
